package com.saturday.common.util;

import com.alibaba.fastjson.JSONObject;
import io.jsonwebtoken.*;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.util.Date;
import java.util.Map;

public class JwtTokenUtils {

    private static final String AUDIENCE = "saturday";

    /**
     * jwt 实际生成token
     *
     * @param userDetails userId: 用户编码
     *                    username：用户登陆名
     * @return
     */
    public static String generateToken(String sessionId, Map<String, Object> userDetails, Date issueAt, long expire, String jwtSecret) {
        if (StringUtils.isBlank(sessionId)) {
            throw new RuntimeException("sessionId can't be empty!");
        }
        String userDetailsStr = null;
        if (MapUtils.isNotEmpty(userDetails)) {
            userDetailsStr = JSONObject.toJSONString(userDetails);
        }
        return Jwts.builder().setId(sessionId)
                .setSubject(userDetailsStr)
                .setIssuedAt(issueAt)
                .setAudience(AUDIENCE)
                .setExpiration(new Date(System.currentTimeMillis() + expire))
                .signWith(SignatureAlgorithm.HS512, generalKey(jwtSecret)).compact();
    }

    /**
     * 刷新token
     *
     * @param token
     * @param expire
     * @param jwtSecret
     * @return
     */
    public static String refreshToken(String token, long expire, String jwtSecret) {
        Claims claims = Jwts.parser().setSigningKey(generalKey(jwtSecret)).parseClaimsJws(token).getBody();
        return Jwts.builder().setClaims(claims)
                .setExpiration(new Date(System.currentTimeMillis() + expire))
                .signWith(SignatureAlgorithm.HS512, generalKey(jwtSecret)).compact();
    }

    /**
     * 解析sessionId
     *
     * @param token
     * @param secret
     * @return
     */
    public static String getSessionIdFromToken(String token, String secret) {
        return getClaimsFromToken(token, secret).getId();
    }

    /**
     * 验证token
     *
     * @param token
     * @param jwtSecret
     * @return
     */
    public static Boolean validateToken(String token, String jwtSecret) {
        try {
            Jwts.parser().setSigningKey(generalKey(jwtSecret)).requireAudience(AUDIENCE).parseClaimsJwt(token);
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }

    private static Date getExpirationDateFromToken(String token, String jwtSecret) {
        return getClaimsFromToken(token, jwtSecret).getExpiration();
    }

    private static SecretKey generalKey(String jwtSecret) {
        byte[] encodedKey = Base64.decodeBase64(jwtSecret);
        return new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");
    }

    public static Claims getClaimsFromToken(String token, String jwtSecret) {
        return Jwts.parser().setSigningKey(generalKey(jwtSecret)).parseClaimsJws(token).getBody();
    }

}
